package cn.yunyichina.provider.guide.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.rpc.service.GenericException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yy.interfaces.service.ZhyyService;
import com.yy.interfaces.vo.clinicpay.MZFeeDetailRequest;
import com.yy.interfaces.vo.microsite.HospitalRequest;

import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.ClinicService;
import cn.yunyichina.provider.framework.dubbo.service.HisifaceService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.guide.GuideConstants;
import cn.yunyichina.provider.guide.dao.DeptPositionDao;
import cn.yunyichina.provider.guide.dao.InstanceDao;
import cn.yunyichina.provider.guide.dao.InstanceNodeDao;
import cn.yunyichina.provider.guide.dao.InstanceRelationDao;
import cn.yunyichina.provider.guide.dao.RegisterStatusDao;
import cn.yunyichina.provider.guide.dao.TemplateDao;
import cn.yunyichina.provider.guide.entity.ClinicRecordVo;
import cn.yunyichina.provider.guide.entity.Instance;
import cn.yunyichina.provider.guide.entity.InstanceNode;
import cn.yunyichina.provider.guide.entity.InstanceRelation;
import cn.yunyichina.provider.guide.entity.RegisterRecord;
import cn.yunyichina.provider.guide.entity.RegisterStatus;
import cn.yunyichina.provider.guide.entity.Template;
import cn.yunyichina.provider.guide.util.GroovyShellYYT;
import cn.yunyichina.provider.iface.entity.ErrorCodeDefine;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.guide.GuideRegisterStatusVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.leads.ClinicAddressInfoVo;
import cn.yunyichina.provider.iface.entity.hisiface.leads.ClinicAddressInfoVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.leads.RegisterGuideInfoVo;
import cn.yunyichina.provider.iface.entity.hisiface.leads.RegisterGuideInfoVoResponse;
import cn.yunyichina.utils.commons.IDUtils;
import cn.yunyichina.utils.convert.JsonUtils;

/**
 * 导医实例
 * @author adriftor
 *
 */
@Service("guideinstanceServiceImpl")
public class GuideInstanceServiceImpl  {
	
	private static final Logger logger = LoggerFactory.getLogger(GuideInstanceServiceImpl.class);
	
	private static Map<String,String> mapClinicType = new HashMap<String,String>();
	
	static {
		mapClinicType.put("drug", "取药");
		mapClinicType.put("exam", "检查");
		mapClinicType.put("check", "检验");
	}
	
	/**
	 * 验证开启或结束规则(节点的开启和结束规则)
	 * @param runRule 规则
	 * @param allRelationCompleteFlag 所有分支规则是否都已经完成
	 * @param relationCount 分支数量
	 * @param hasCompleteRelationCount 已经完成的分支数量
 	 * @return
	 */
	private static boolean parseRunRule(String runRule,int relationCount,int hasCompleteRelationCount){
		if (StringUtils.isBlank(runRule)) {
			return true;
		}
		if (relationCount <= 0) {
			return true;
		}
		if (runRule.equalsIgnoreCase("all")) {
			if (hasCompleteRelationCount>=relationCount) {
				return true;
			}
		}
		else if (runRule.matches("\\d+%")) {
			runRule = runRule.substring(0,runRule.indexOf("%"));
			int per = Integer.parseInt(runRule);
			if (per > 100) {
				per = 100;
			}
			if (100*hasCompleteRelationCount/relationCount>=per) {
				return true;
			}
		}
		else if (runRule.matches("\\d+")) {
			int count = Integer.parseInt(runRule);
			if (hasCompleteRelationCount>=count) {
				return true;
			}

		}
		return false;
	}
	
	/**
	 * 解析并且给url的参数赋值,如http://abc.ed.com?order_no={{order_no}}
	 * @param url 
	 * @param param 包含参数值的对象
	 * @return
	 */
	public static String parseUrl(String url,JSONObject param) {
		
		logger.info("parseUrl入参："+url);
		if (StringUtils.isBlank(url)) {
			return url;
		}
		
		if (url.indexOf("{{")> 0) {
			Pattern p = Pattern.compile("(?i)\\{\\{(\\s*[\\w_\\d]+\\s*)\\}\\}");
			Matcher m = p.matcher(url);
			StringBuffer sb = new StringBuffer();
			while (m.find()) {
				String fieldName = m.group(1).trim().toLowerCase();
				if (param.containsKey(fieldName)) {
					m.appendReplacement(sb, param.getString(fieldName));
				}
				else {
					logger.error(fieldName+"参数未传入值");
//					m.appendReplacement(sb, "null");
					//如果参数没有传入，返回空串，结果是模板点击失效
					return "";
//					throw new CallException(ErrorCodeDefine.MESSAGE_VALUE, fieldName+"参数未传入值");
				}
				
				
			}
			m.appendTail(sb);
			url = sb.toString();
		}
		logger.info("parseUrl后："+url);
		return url;
	}
	
	/**
	 * 人民币，单位分转换为元
	 * @param amount
	 * @return
	 */
	public static String transformRMB(Integer amount) {
		if (amount == null || amount == 0) {
			return "0";
		}
		BigDecimal b = new BigDecimal(amount);
		return b.divide(new BigDecimal(100)).toString();
	}
	

	@Resource
	private InstanceDao instanceDao;
	
	@Resource
	private TemplateDao templateDao;
	
	
	@Resource
	private InstanceNodeDao instanceNodeDao;
	@Resource
	private InstanceRelationDao instanceRelationDao;
	@Resource
	private GuideTemplateServiceImpl guideTemplateService;
	
	@Resource
	private DeptPositionDao deptPositionDao;
	@Resource
	private RegisterStatusDao registerStatusDao;
	/**
	 * 计算缴费节点总金额
	 * @param userId
	 * @param orderNos 多个，用逗号分隔，如："'Y20170001','Y20170002'"
	 * @return
	 */
	public Integer calClinicTotalAmount(String userId,String orderNos) {
		try{
			
			StringBuilder sb = new StringBuilder("select sum(total_fee) as total_fee from (");
			for (int k = 1;k<=10;k++) {
				sb.append("select sum(total_fee) as total_fee from biz_clinic_record_"+k+" where user_id='"+userId+"' and  order_no in ("+orderNos+")");

				if (k != 10) {
					sb.append(" union ");
				}
				
			}
			sb.append(") t");
			List listRegister = BaseService.getBaseClient().queryZhyySql(sb.toString());
			if (CollectionUtils.isNotEmpty(listRegister)) {
				Object v = ((Map)listRegister.get(0)).get("total_fee");
				if (v != null) {
					return Integer.parseInt(v.toString());
				}
			}
			return 0;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
		}
	
	}

	/**
	 * 手动完成一个流程节点
	 * <br>yyt.guide.guideinstance.node.complete
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param instanceId
	 * @param nodeId
	 */
	public String completeGuideInstanceNode(String strJson) {
		try{
			JSONObject param = JsonUtils.parseObject(strJson);
			String instanceId = param.getString("instance_id");
			String nodeId = param.getString("node_id");
			Instance instance = instanceDao.selectById(instanceId);
			if (instance != null && instance.getRunStatus().equals(GuideConstants.INSTANCE_RUN_STATUS_RUNNING)) {
				InstanceNode instanceNode = instanceNodeDao.selectById(nodeId);
				if (instanceNode != null) {
					instanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_END);
					instanceNodeDao.update(instanceNode);
				}
				else {
					return "节点不存在";
				}
			}
			else {
				return "导医已经结束";
			}
			
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"手动完成一个流程节点异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"手动完成一个流程节点异常",ex);
		}
		return "SUCCESS";
	}
	/**
	 * 流程节点正常完成
	 * @param instanceId
	 */
	private void completeInstance(InstanceNode instanceNode) {
		logger.info(JsonUtils.toJsonString(instanceNode));
		Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
		instance.setRunStatus(GuideConstants.INSTANCE_RUN_STATUS_END);
		instanceDao.update(instance);
		
		logger.info("completeInstance--ok");
		
	}
	
	/**
	 * 某个节点运行结束
	 * @param instanceNode
	 * @param relationCount 目标分支数量
	 * @param hasCompleteRelationCount 已经通过的目标分支数量
	 */
	private void endNode(InstanceNode instanceNode) {

		logger.info(JsonUtils.toJsonString(instanceNode));
		
		//门诊节点因要自动根据订单产生节点，因此设置成不可结束
		if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC_PAY) {
			return;
		}
		InstanceRelation relation = new InstanceRelation();
		relation.setInstanceId(instanceNode.getInstanceId());
		relation.setStartNodeId(instanceNode.getId());
		List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
		int relationCount = listRelation.size();
		int hasCompleteRelationCount = 0;
		for (InstanceRelation thisRelation : listRelation) {
			if (GuideConstants.RELATION_STATUS_PASS.equalsIgnoreCase(thisRelation.getStatus())) {
				hasCompleteRelationCount++;
			}
		}
		
		if (parseRunRule(instanceNode.getEndRunRule(), relationCount, hasCompleteRelationCount)) {
			logger.info("有下一步,并且符合节点结束规则，"+instanceNode.getNodeName());
			instanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_END);
			instanceNode.setEndTime(GuideConstants.YYYYMMDDHHMMSS.format(new Date()));
			instanceNodeDao.update(instanceNode);
		}
		else {
			logger.info(" 不符合节点结束规则，"+instanceNode.getNodeName()+"relationCount="+relationCount+",hasCompleteRelationCount="+hasCompleteRelationCount);
		}
		
		logger.info("endNode--ok");
	}
	
	/**
	 * 由订单生成的节点（类型40），根据HIS返回的信息生成子节点
	 * @param instanceNode
	 */
	public void genAddressNode(String instanceNodeId,List<ClinicAddressInfoVoResponse> listAddressInfo) {
		try {
			InstanceNode instanceNode = instanceNodeDao.selectById(instanceNodeId);
			
			logger.info(JsonUtils.toJsonString(instanceNode));
			if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC_ORDER) {
//				JSONArray newJsonNodeArr = genAutoJsonNodeArr(instanceNode.getRemarks());
				if (listAddressInfo == null || listAddressInfo.size() == 0) {
					logger.info("没有地址节点信息");
					return;
				}
				logger.info(JsonUtils.toJsonString(listAddressInfo));
				//检查是否已经自动生成了节点
				InstanceRelation relationQuery = new InstanceRelation();
				relationQuery.setInstanceId(instanceNode.getInstanceId());
				relationQuery.setStartNodeId(instanceNode.getId());
				Long count = instanceRelationDao.selectCount(relationQuery);
				logger.info("已经自动生成的节点数"+count);
				if (count > 0) {
					return;
				}
	//			List<InstanceRelation> listInstanceRelation = instanceRelationDao.select(relation);
	//
	//			//标记不需要新增节点
	//			int size = arrJsonNode.size();
	//			if (CollectionUtils.isNotEmpty(listInstanceRelation)) {
	//				for (InstanceRelation thisRelation : listInstanceRelation) {
	//					InstanceNode toInstanceNode = instanceNodeDao.selectById(thisRelation.getEndNodeId());
	//					
	//					//此节点是否需要新增
	//					for (int i = 0;i<size;i++) {
	//						JSONObject jsonNode = arrJsonNode.getJSONObject(i);
	//						if (toInstanceNode.getNodeName().equals(jsonNode.getString("name"))) {
	//							//标记此节点已经存在
	//							jsonNode.put("is_new",false);
	//						}
	//					}
	//				}
	//				
	//			}
	//			
	//			//去掉不需要新增节点
	//			JSONArray tempArr = new JSONArray();
	//			for (int i = 0;i<size;i++) {
	//				JSONObject jsonNode = arrJsonNode.getJSONObject(i);
	//				if ( ! jsonNode.containsKey("is_new")) {
	//					tempArr.add(jsonNode);
	//				}
	//			}
	//			arrJsonNode = tempArr;
				int size = listAddressInfo.size();
				
				
				for (int i = 0;i<size;i++) {
//					JSONObject jsonNode = newJsonNodeArr.getJSONObject(i);
					ClinicAddressInfoVoResponse addressInfo = listAddressInfo.get(i);
					InstanceNode newInstanceNode = new InstanceNode();
					newInstanceNode.setId(IDUtils.getUUID32());
					newInstanceNode.setInstanceId(instanceNode.getInstanceId());
					
					newInstanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_NOT_START);
					newInstanceNode.setTemplateNodeId("");
					
					newInstanceNode.setNodeName(addressInfo.getPlaceName()+"-"+addressInfo.getDeptName());
					
					//节点过程类型
					newInstanceNode.setNodeProcType(GuideConstants.NODE_PROC_TYPE_HIS_ADDRESS);
//					if (jsonNode.containsKey("node_proc_type") && StringUtils.isNotBlank(jsonNode.getString("node_proc_type"))) {
//						newInstanceNode.setNodeProcType(jsonNode.getInteger("node_proc_type"));
//					}
					
					//节点类型
					newInstanceNode.setNodeType(GuideConstants.NODE_TYPE_AUTO);
//					if (jsonNode.containsKey("rule_exp") && StringUtils.isNotBlank(jsonNode.getString("rule_exp"))) {
//						newInstanceNode.setNodeType(GuideConstants.NODE_TYPE_RULE);
//					}
					
					
//					if (jsonNode.containsKey("photo")) {
//						newInstanceNode.setPhoto(jsonNode.getString("photo"));
//					}
//					if (jsonNode.containsKey("remarks")) {
//						newInstanceNode.setRemarks(jsonNode.getString("remarks"));
//					}
//					if (jsonNode.containsKey("url")) {
//						newInstanceNode.setUrl(jsonNode.getString("url"));
//					}
//					if (jsonNode.containsKey("x")) {
//						newInstanceNode.setX(jsonNode.getDouble("x"));
//					}
//					if (jsonNode.containsKey("y")) {
//						newInstanceNode.setY(jsonNode.getDouble("y"));
//					}
					
					String clinicTypeName = mapClinicType.get(addressInfo.getType()); 
					if (clinicTypeName == null) {
						clinicTypeName = "";
					}
					String remarks = "请您到"+addressInfo.getPlaceName()+clinicTypeName;
					if (StringUtils.isNotBlank(addressInfo.getAddress())) {
						remarks += "\n位置："+addressInfo.getAddress();
					}
					
					newInstanceNode.setRemarks(remarks);
					instanceNodeDao.insert(newInstanceNode);
					
					InstanceRelation newRelation = new InstanceRelation();
					newRelation.setEndNodeId(newInstanceNode.getId());
					newRelation.setId(IDUtils.getUUID32());
					newRelation.setInstanceId(newInstanceNode.getInstanceId());
					
					newRelation.setRuleExp("");
//					if (jsonNode.containsKey("rule_exp") && StringUtils.isNotBlank(jsonNode.getString("rule_exp"))) {
//						relation.setRuleExp(jsonNode.getString("rule_exp"));
//					}

					
					newRelation.setStartNodeId(instanceNode.getId());
					newRelation.setTemplateRelationId("");
					
					instanceRelationDao.insert(newRelation);
				}
				logger.info("autoGenerateNode--ok");
			}
			else {
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "非门诊缴费不能自动生成节点");
			}
		
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
		}
	}
	/**
	 * 门诊缴费节点，根据缴费订单生成节点。
	 * 产生的节点数和订单数相同
	 * @param instanceNode
	 */
	public void genNodeByOrder_bak(InstanceNode instanceNode ) {
//		try {
//			logger.info(JsonUtils.toJsonString(instanceNode));
//			
//			if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC) {
//				Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
//				
//				OrderExtVo order = BaseService.getBaseClient().getOrderByOrderNo(instance.getOrderNo());
//				Calendar c = Calendar.getInstance();
//				//小时
//				c.add(Calendar.HOUR_OF_DAY, -2000);
//
////				String maxTime = instanceNodeDao.selectMaxOrderTime(instance.getId());				
////				if (StringUtils.isNotBlank(maxTime)) {
////					c.setTime(GuideConstants.YYYYMMDDHHMMSS.parse(maxTime));
////				}
//				
//				List<OrderExtVo> listNewOrder = instanceDao.selectOrderNotMatch(GuideConstants.YYYYMMDDHHMMSS.format(c.getTime()), order.getMzFeeId(), instance.getId());
//				
//				logger.info(JsonUtils.toJsonString(listNewOrder));
//				if (listNewOrder == null || listNewOrder.size() == 0) {
//					logger.info("没有新的代缴费节点");
//					return;
//				}
//				
//				int size = listNewOrder.size();
//				
//				for (int i = 0;i<size;i++) {
//					OrderExtVo orderVo = listNewOrder.get(i);
//					InstanceNode newInstanceNode = new InstanceNode();
//					newInstanceNode.setId(IDUtils.getUUID32());
//					newInstanceNode.setInstanceId(instanceNode.getInstanceId());
//					
//					newInstanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_NOT_START);
//					newInstanceNode.setTemplateNodeId("");
//					
//					newInstanceNode.setOrderNo(orderVo.getOrderNo());
//					newInstanceNode.setNodeName("待缴费："+transformRMB(orderVo.getTotalAmount()));
//					
//					//节点过程类型
//					newInstanceNode.setNodeProcType(GuideConstants.NODE_PROC_TYPE_BY_ORDER);
//
//					//节点类型
//					newInstanceNode.setNodeType(GuideConstants.NODE_TYPE_AUTO);
//					newInstanceNode.setRemarks(orderVo.getHisMessage());
//					
//					String remarks = "您有一笔待缴费("+transformRMB(orderVo.getTotalAmount())+")";
//					newInstanceNode.setRemarks(remarks);
//					
//					newInstanceNode.setUrl("listOrderItem.ftl?order_no="+orderVo.getOrderNo());//listItem 地址
//					
//					instanceNodeDao.insert(newInstanceNode);
//					
//					InstanceRelation relation = new InstanceRelation();
//					relation.setEndNodeId(newInstanceNode.getId());
//					relation.setId(IDUtils.getUUID32());
//					relation.setInstanceId(newInstanceNode.getInstanceId());
//					
//					relation.setRuleExp("");
//					
//					relation.setStartNodeId(instanceNode.getId());
//					relation.setTemplateRelationId("");
//					
//					instanceRelationDao.insert(relation);
//				}
//				
//				//更新 Remarks
//				if (size > 0) {
//					InstanceRelation relation = new InstanceRelation();
//					relation.setInstanceId(instance.getId());
//					relation.setStartNodeId(instanceNode.getId());
//					List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
//					
//					Integer totalAmount = instanceDao.calClinicTotalAmount(instance.getId());
//					if (totalAmount == null) {
//						totalAmount = 0;
//					}
//							
//					String msg = "您有"+listRelation.size()+"笔待缴费（"+transformRMB(totalAmount)+"）";
//					instanceNode.setRemarks(msg);
//					instanceNodeDao.update(instanceNode);
//				}
//				
//				logger.info("autoGenerateNode--ok");
//			}
//			else {
//				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "非门诊缴费不能自动生成节点");
//			}
//		
//		}
//		catch (Exception ex) {
//			logger.error(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
//			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
//		}
	}
	/**
	 * 门诊缴费节点，根据缴费订单生成节点。
	 * 产生的节点数和订单数相同
	 * @param instanceNode
	 */
	public void genOrderNode(InstanceNode instanceNode ) {
		try {
			logger.info(JsonUtils.toJsonString(instanceNode));
			
			if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC_PAY && GuideConstants.NODE_RUN_STATUS_RUNNING.equals(instanceNode.getRunStatus())) {
				Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
				
				//查找已经由门诊生成的节点的
				InstanceNode queryNode = new InstanceNode();
				queryNode.setInstanceId(instanceNode.getInstanceId());
				queryNode.setNodeProcType(GuideConstants.NODE_PROC_TYPE_CLINIC_ORDER);
				
				List<InstanceNode> listInstanceNodeOfOrder = instanceNodeDao.select(queryNode);
				Map<String,String> mapExist = new HashMap<>();
				
				if (CollectionUtils.isNotEmpty(listInstanceNodeOfOrder)) {
					for (InstanceNode thisNode : listInstanceNodeOfOrder) {
						mapExist.put(thisNode.getOrderNo(), thisNode.getId());
					}
				}
				
				Calendar c = Calendar.getInstance();
				//12小时之内的缴费
				c.add(Calendar.HOUR_OF_DAY, -12);

//				String maxTime = instanceNodeDao.selectMaxOrderTime(instance.getId());				
//				if (StringUtils.isNotBlank(maxTime)) {
//					c.setTime(GuideConstants.YYYYMMDDHHMMSS.parse(maxTime));
//				}
				//选择最近2个小时内发生缴费的导医
				//逐个匹配
				
				//从订单表查找新增的们正缴费订单
//				List<OrderExtVo> listNewOrder = instanceDao.selectOrderNotMatch(instance.getMzFeeId(), instance.getUserId());

				ClinicRecordVo clinicRecord = new ClinicRecordVo();
				clinicRecord.setUserId(instance.getUserId());
				if (StringUtils.isEmpty(instance.getMzFeeId())) {
					clinicRecord.setMzfeeId("test");
				}
				else {
					clinicRecord.setMzfeeId(instance.getMzFeeId());
				}
 				
				clinicRecord.setHospitalCode(instance.getOrgCode());
				clinicRecord.setClinicStatuss("0,1,7");
				clinicRecord.setBeginCreateTime(GuideConstants.YYYYMMDDHHMMSS.format(c.getTime()));
				List<OrderExtVo> listNewOrder = this.listGuideInstanceOrderOfClinicRecord(JsonUtils.toJsonString(clinicRecord));
				if (CollectionUtils.isNotEmpty(listNewOrder)) {
					int size = listNewOrder.size();
					
					logger.info(JsonUtils.toJsonString(listNewOrder));
					if (listNewOrder == null || listNewOrder.size() == 0) {
						logger.info("没有新的代缴费节点");
						return;
					}
//					if (listNewOrder.size() == mapExist.size()) {
//						logger.info("没有新增的代缴费节点");
//						return;
//					}
					//是否有新的节点
					boolean hasNewNode = false;
					String orderNos = "";
					for (int i = 0;i<size;i++) {
						OrderExtVo order = listNewOrder.get(i);
						orderNos += ",'"+order.getOrderNo()+"'";
						if (mapExist.containsKey(order.getOrderNo())) {
							continue;
						}
						hasNewNode = true;
						InstanceNode newInstanceNode = new InstanceNode();
						newInstanceNode.setId(IDUtils.getUUID32());
						newInstanceNode.setInstanceId(instanceNode.getInstanceId());
						
						newInstanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_NOT_START);
						newInstanceNode.setTemplateNodeId("");
						
						newInstanceNode.setOrderNo(order.getOrderNo());
						newInstanceNode.setNodeName("待缴费："+transformRMB(order.getTotalAmount()));
						
						//节点过程类型
						newInstanceNode.setNodeProcType(GuideConstants.NODE_PROC_TYPE_CLINIC_ORDER);

						//节点类型
						newInstanceNode.setNodeType(GuideConstants.NODE_TYPE_AUTO);
						newInstanceNode.setRemarks(order.getHisMessage());
						
						String remarks = "您有一笔待缴费("+transformRMB(order.getTotalAmount())+")";
						newInstanceNode.setRemarks(remarks);
						
//						newInstanceNode.setUrl("listOrderItem.ftl?order_no="+order.getOrderNo());//listItem 地址
						
						instanceNodeDao.insert(newInstanceNode);
						
						InstanceRelation relation = new InstanceRelation();
						relation.setEndNodeId(newInstanceNode.getId());
						relation.setId(IDUtils.getUUID32());
						relation.setInstanceId(newInstanceNode.getInstanceId());
						
						relation.setRuleExp("");
						
						relation.setStartNodeId(instanceNode.getId());
						relation.setTemplateRelationId("");
						
						instanceRelationDao.insert(relation);
					} //for
					
					if ( ! hasNewNode) {
						//没有新的节点，直接返回，不在做后续的统计
						return;
					}
					
					orderNos = orderNos.substring(1);
					
					//更新 Remarks
					InstanceRelation relation = new InstanceRelation();
					relation.setInstanceId(instance.getId());
					relation.setStartNodeId(instanceNode.getId());
					List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
					Integer totalAmount = this.calClinicTotalAmount(instance.getUserId(),orderNos);
					if (totalAmount == null) {
						totalAmount = 0;
					}
							
					String msg = "您有"+listRelation.size()+"笔待缴费（"+transformRMB(totalAmount)+"）";
					instanceNode.setRemarks(msg);
					instanceNodeDao.update(instanceNode);
					
				}
				
				logger.info("autoGenerateNode--ok");
			}
			else {
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "非门诊缴费不能自动生成节点");
			}
		
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"门诊缴费自动产生节点异常",ex);
		}
	}
	
	
	
	/**
	 * 获取一个导医完整流程
	 * <BR>根据导医流程ID，或挂号记录ID，或用户ID获取一个导医流程信息。流程ID、挂号记录ID、用户ID不能同时为空
	 * <br>yyt.guide.guideinstance.get
	 * @param orgCode
	 * @param appCode
	 * @param orderNo
	 * @param userId
	 * @param instanceId
	 * @return 返回一个完整的流程，包含节点、规则信息。找不到则返回null
	 */
	public Instance getGuideInstance(String strJson) {
		JSONObject param = JsonUtils.parseObject(strJson);
		return getGuideInstanceReal(param.getString("org_code"), param.getString("app_code"), param.getString("order_no"), param.getString("user_id"), param.getString("instance_id"));
	}
	/**
	 * 获取一个流程的全部信息
	 * yyt.guide.guideinstance.full.get
	 * @param instanceId
	 * @return 
	 */
	public Instance getGuideInstanceFull(String instanceId) {
		logger.info("getFullInstance:"+instanceId);
		Instance instance = instanceDao.selectById(instanceId);
		InstanceNode node = new InstanceNode();
		node.setInstanceId(instanceId);
		List<InstanceNode> listNode = instanceNodeDao.select(node);
		instance.setListNode(listNode);
		
		//url解析，url变量名称，参考Instance对象
		JSONObject urlParam = JsonUtils.parseObject(instance);
		for (InstanceNode instanceNode : listNode) {
			String url = instanceNode.getUrl();
			if (StringUtils.isBlank(url)) {
				parseUrl(url, urlParam);
			}
		}
		
		InstanceRelation relation = new InstanceRelation();
		relation.setInstanceId(instanceId);
		List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
		instance.setListRelation(listRelation);
		logger.info(JsonUtils.toJsonString(instance));
		return instance;
		
		
	}
	/**
	 * 获取一个流程的全部信息
	 * yyt.guide.guideinstance.full.map.get
	 * @param instanceId
	 * @return 
	 */
	public JSONObject getGuideInstanceFullMap(String instanceId) {
		logger.info("getFullInstance:"+instanceId);
		Instance instance = instanceDao.selectById(instanceId);
		InstanceNode node = new InstanceNode();
		node.setInstanceId(instanceId);
		List<InstanceNode> listNode = instanceNodeDao.select(node);
		instance.setListNode(listNode);
		Map<String,InstanceNode> mapNode = new LinkedHashMap<>();
		
		//url解析，url变量名称，参考Instance对象
		JSONObject urlParam = JsonUtils.parseObject(instance);
		for (InstanceNode instanceNode : listNode) {
			String url = instanceNode.getUrl();
			if (StringUtils.isBlank(url)) {
				parseUrl(url, urlParam);
			}
			mapNode.put(instanceNode.getId(), instanceNode);
		}
		
		InstanceRelation relation = new InstanceRelation();
		relation.setInstanceId(instanceId);
		List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
		Map<String,InstanceRelation> mapRelation = new LinkedHashMap<>();
		for (InstanceRelation relationThis : listRelation) {
			mapRelation.put(relationThis.getId(), relationThis);
		}
		
		
		instance.setListRelation(listRelation);
		
		JSONObject jsonInstance = JsonUtils.parseObject(instance);
		jsonInstance.put("map_node", mapNode);
		jsonInstance.put("map_relation",mapRelation);
		
		
		logger.info(JsonUtils.toJsonString(jsonInstance));
		return jsonInstance;
		
		
	}
	
	/**
	 * 从HIS获取缴费后地址新消息
	 * yyt.guide.guideinstance.his.address.info.get
	 * @param nodeId 节点ID
	 * @return 如果没有获取到，返回null
	 */
	public List<ClinicAddressInfoVoResponse> getGuideInstanceHisAddressInfo(String orderNo) {
		logger.info(orderNo);
		if (orderNo.startsWith("{")) {
			JSONObject param = JsonUtils.parseObject(orderNo);
			orderNo = param.getString("order_no");
		}
		if (StringUtils.isBlank(orderNo)) {
			logger.error("orderNo为空");
			return null;
		}
		InstanceNode queryNode = new InstanceNode();
		queryNode.setOrderNo(orderNo);
		List<InstanceNode> listNode = instanceNodeDao.select(queryNode);
		if (CollectionUtils.isEmpty(listNode)) {
			logger.warn(orderNo+"对应的订单节点不存在");
			return null;
		}
		return getHisAddressInfo(listNode.get(0));
	}
	/**
	 * 调用HIS获取挂号状态<br>
	 * yyt.guide.guideinstance.his.register.status.get
	 * @param instance
	 * @return 如果无法获取，返回null
	 */
	public RegisterGuideInfoVoResponse getGuideInstanceHisRegisterStatus(String orderNo) {
		
		//yyt.clinic.mzfee.detail.get
		logger.info(orderNo);
		if (orderNo.startsWith("{")) {
			JSONObject param = JsonUtils.parseObject(orderNo);
			orderNo = param.getString("order_no");
			
			
		}
		if (StringUtils.isBlank(orderNo)) {
			logger.error("orderNo为空");
			return null;
		}
		
		Instance queryInstance = new Instance();
		queryInstance.setOrderNo(orderNo);
		List<Instance> listInstance = instanceDao.select(queryInstance);
		if (CollectionUtils.isEmpty(listInstance)) {
			logger.error(orderNo+"对应的导医不存在");
			return null;
		}
		return getHisRegisterStatus(listInstance.get(0));
	}
	private ZhyyService getZhyyService(String hospitalCode) {
		return SpringContextHolder.getBean(hospitalCode+"Service");
	}
	/**
	 * 获取门诊缴费明细
	 * yyt.guide.guideinstance.mz.fee.detail.list.get
	 * @param strJson mz_fee_id,org_code
	 * @return
	 */
	public String getGuideInstanceMzfeeDetailList(String strJson) {
		try {
			logger.info(strJson);
			JSONObject param = JsonUtils.parseObject(strJson);
			MZFeeDetailRequest request = JsonUtils.parseObject(strJson,MZFeeDetailRequest.class);
			if (StringUtils.isNotBlank(request.getMzFeeId()) && StringUtils.isNotBlank(param.getString("org_code"))) {
				ZhyyService zhyyService = this.getZhyyService(param.getString("org_code"));
				if (StringUtils.isBlank(request.getBranchCode())) {
					request.setBranchCode("");
				}
				
				logger.info("调用参数:"+JsonUtils.toJsonString(request));
				com.yy.interfaces.vo.Response response = zhyyService.getMZFeeDetail(request);
				logger.info("调用结果:"+JsonUtils.toJsonString(response));
				if (response != null && response.getResult() != null) {
					return JsonUtils.toJsonString(response.getResult());
				}
				
			}
			return null;
		} catch (GenericException e) {
			logger.error("获取门诊缴费明细失败",e);
		}
		return null;
		
		
	}
	/**
	 * 获取门诊缴费明细
	 * yyt.guide.guideinstance.mz.fee.detail.list.get
	 * @param strJson mz_fee_id
	 * @return
	 */
	public String getGuideInstanceMzfeeDetailList_YYT(String strJson) {
		JSONObject param = JsonUtils.parseObject(strJson);
		if (StringUtils.isNotBlank(param.getString("mz_fee_id"))) {
			logger.info("调用mzfee"+JsonUtils.toJsonString(param));
			Response response = ClinicService.callHumpFromInternal("yyt.clinic.mzfee.detail.get", JsonUtils.toJsonString(param));
			logger.info(JsonUtils.toJsonString(response));
			if (response != null) {
				Map<String,Object> resultMap = JsonUtils.parseObject(response.getResult());
				if (resultMap != null) {
					Object list = resultMap.get("list");
					if (list != null) {
						String strList = JsonUtils.toJsonString(list);
						return strList;
					}
				}
			}
		}
		return null;
		
		
	}
	
	/**
	 * 根据order_no获取一条缴费记录
	 * yyt.guide.guideinstance.order.of.clinic.record.get
	 * @param strJson
	 * 
	 * @param order_no
	 * @return
	 */
	public JSONObject getGuideInstanceOrderOfClinicRecord(String strJson) {
		
		JSONObject param = JsonUtils.parseObject(strJson);
		if (StringUtils.isEmpty(param.getString("order_no"))) {
			throw new CallException(ErrorCodeDefine.GUIDE_VALUE, "order_no参数缺失");
		}
		List<OrderExtVo> listOrder = this.listGuideInstanceOrderOfClinicRecord(strJson);
		if (CollectionUtils.isNotEmpty(listOrder)) {
			JSONObject jsonObj  = JsonUtils.parseObject(listOrder.get(0));
			logger.info(JsonUtils.toJsonString(jsonObj));
			if (StringUtils.isNotBlank(jsonObj.getString("mz_fee_id"))) {
//				String sql = "select * from data_mz_fee_detail where mz_fee_id='"+jsonObj.getString("mz_fee_id")+"' group by item_id";
//				List listItem = BaseService.getBaseClient().queryZhyySql(sql);
				
				jsonObj.put("list_item", this.getGuideInstanceMzfeeDetailList(JsonUtils.toJsonString(jsonObj)));
			}
			return jsonObj;
			
		}
		return null;
	}
	/**
	 * 获取一个导医完整流程
	 * <BR>根据导医流程ID，或挂号记录ID，或用户ID获取一个导医流程信息。流程ID、挂号记录ID、用户ID不能同时为空
	 * <br>yyt.guide.guideinstance.get
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param orderNo
	 * @param userId
	 * @param instanceId
	 * @return 返回一个完整的流程，包含节点、规则信息。找不到则返回null
	 */
	private Instance getGuideInstanceReal(String orgCode,String appCode,String orderNo,String userId,String instanceId) {
		try {
			logger.info("instanceId="+instanceId+",orderNo="+orderNo+",userId="+userId);
			
			if (StringUtils.isNotBlank(instanceId)) {
				return this.getGuideInstanceFull(instanceId);
			}
			else if (StringUtils.isNotBlank(orderNo)) {
				Instance instance = new Instance();
				instance.setOrgCode(orgCode);
				instance.setOrderNo(orderNo);
				List<Instance> listInstance = instanceDao.select(instance);
				if (CollectionUtils.isEmpty(listInstance)) {
					
					return  this.startGuideInstanceReal(orderNo);

				}
				else {
					return getGuideInstanceFull(listInstance.get(0).getId());
				}
			}
			else if (StringUtils.isNotBlank(userId)) {
				//当天最新创建的未结束导医流程
				Instance instance = new Instance();
				instance.setUserId(userId);
				
				//当天
				Calendar c = Calendar.getInstance();
				instance.setBeginCreatedTime(GuideConstants.YYYYMMDD.format(c.getTime())+" 00:00:00");
				
				instance.setRunStatus(GuideConstants.INSTANCE_RUN_STATUS_RUNNING);
				instance.setOrgCode(orgCode);
				List<Instance> listInstance = instanceDao.select(instance);
				if (CollectionUtils.isNotEmpty(listInstance)) {
					return getGuideInstanceFull(listInstance.get(0).getId());
				}
				return null;
			}
			else{
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "参数错误");
			}
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取一个导医完整流程异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取一个导医完整流程异常",ex);
		}
	}
	
	/**
	 * 获取挂号信息
	 * <br>yyt.guide.guideinstance.register.record.get
	 * @param strJson
	 * @param orgCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 * @throws CallException 如果查不到挂号信息，抛出异常
	 */
	public OrderExtVo getGuideInstanceRegisterRecord(String orderNo) {
		try{
			return BaseService.getBaseClient().getOrderByOrderNo(orderNo);
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
		}

	
	}
	
	/**
	 * 从HIS获取缴费后地址新消息
	 * @param nodeId 节点ID
	 * @return 如果没有获取到，返回null
	 */
	public List<ClinicAddressInfoVoResponse> getHisAddressInfo(InstanceNode instanceNode) {
		logger.info(JsonUtils.toJsonString(instanceNode));

		Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
		
		//调用HIS接口
		ClinicAddressInfoVo clinicAddressInfoVo = new ClinicAddressInfoVo();
		clinicAddressInfoVo.setYytOrdNum(instanceNode.getOrderNo());
		clinicAddressInfoVo.setAppCode(instance.getPlatformCode());
		clinicAddressInfoVo.setHospitalCode(instance.getOrgCode());
		
		List<ClinicAddressInfoVoResponse> listAddressInfo = null;
		
		try {
			logger.info("clinicAddressInfoVo入参："+JsonUtils.toJsonString(clinicAddressInfoVo));
			ResCommon<List<ClinicAddressInfoVoResponse>> res = HisifaceService.getHisifaceClient().getClinicAddressInfo(clinicAddressInfoVo);
			logger.info("resAddress-"+JsonUtils.toJsonString(res));
			listAddressInfo = res.getResult();			
			if (listAddressInfo == null) {
				logger.error("从HIS获取缴费的路由信息异常：null,"+JsonUtils.toJsonString(instanceNode));
			}
			
			return listAddressInfo;
		} catch (Exception e) {
			logger.error("获取缴费后路由信息异常"+JsonUtils.toJsonString(instanceNode),e);
		}
		
		return null;
		
	}
	
	/**
	 * 调用HIS获取挂号状态<br>
	 * @param instance
	 * @return 如果无法获取，返回null
	 */
	public RegisterGuideInfoVoResponse getHisRegisterStatus(Instance instance) {
		logger.info(JsonUtils.toJsonString(instance));

		Calendar c = Calendar.getInstance();
		//3天内，测试时放宽
		c.add(Calendar.DATE, -30);
		//调用HIS接口
		RegisterGuideInfoVo registerGuideInfoVo = new RegisterGuideInfoVo();
		registerGuideInfoVo.setBeginDate(GuideConstants.YYYYMMDD.format(c.getTime()));
		c = Calendar.getInstance();
		c.add(Calendar.DATE, 1);
		registerGuideInfoVo.setEndDate(GuideConstants.YYYYMMDD.format(c.getTime()));
		registerGuideInfoVo.setHospitalCode(instance.getOrgCode());
		
		registerGuideInfoVo.setPatCardNo(instance.getPatCardNo());
		registerGuideInfoVo.setYytOrdNum(instance.getOrderNo());
		registerGuideInfoVo.setPatCardType(instance.getPatCardType());
		registerGuideInfoVo.setAppCode(instance.getPlatformCode());
		
		RegisterGuideInfoVoResponse registerGuideInfoVoResponse = null;
		
		try {
			logger.info("registerGuideInfoVo="+JsonUtils.toJsonString(registerGuideInfoVo));
			ResCommon<RegisterGuideInfoVoResponse> res = HisifaceService.getHisifaceClient().getRegisterGuideInfo(registerGuideInfoVo);
			logger.info("res="+JsonUtils.toJsonString(res));
			if (res.getResultMessage().indexOf("无记录") >= 0 ) {
				logger.info("HIS没有对应的挂号记录："+JsonUtils.toJsonString(registerGuideInfoVo));
			}
			registerGuideInfoVoResponse = res.getResult();			
			if (registerGuideInfoVoResponse == null) {
				logger.info("从HIS获取挂号状态异常，返回结果为null,"+JsonUtils.toJsonString(instance));
			}
			return registerGuideInfoVoResponse;
			
		} catch (Exception e) {
			logger.error("获取挂号状态信息异常"+JsonUtils.toJsonString(instance),e);
		}
		
		return null;
	}
	
	/**
	 * 获取挂号信息
	 * <br>yyt.guide.guideinstance.register.record.get
	 * @param strJson
	 * @param orgCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 * @throws CallException 如果查不到挂号信息，抛出异常
	 */
	public OrderExtVo getOrderByOrderNo(String orderNo) {
		try{
			RegisterRecord registerRecord = this.getRegisterRecord(orderNo);
			OrderExtVo order = registerRecord.toOrder();
			return order;
//			return BaseService.getBaseClient().getOrderByOrderNo(orderNo);
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
		}

	
	}
	
	/**
	 * 从旧系统获取挂号信息
	 * @param strJson
	 * @param orgCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 * @throws CallException 如果查不到挂号信息，抛出异常
	 */
	public RegisterRecord getRegisterRecord(String orderNo) {

		try{
			StringBuilder sb = new StringBuilder("select * from (");
			for (int k = 1;k<=10;k++) {
				sb.append("select * from biz_register_record_"+k+" where order_no='"+orderNo+"'");
				if (k != 10) {
					sb.append(" union ");
				}
				
			}
			sb.append(") t");
			List listRegister = BaseService.getBaseClient().queryZhyySql(sb.toString());
			if (CollectionUtils.isEmpty(listRegister)) {
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "无法获取挂号记录："+orderNo);
			}
			else {
				return JsonUtils.parseObject(listRegister.get(0), RegisterRecord.class);
			}
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号信息异常",ex);
		}

	
	}

	/**
	 * 处理正在运行的节点
	 * @param instanceNode
	 * @param throwFlagOfNotNext 如果没有匹配到下一步匹配的节点，或者不是正常结束，就抛出异常。
	 */
	public void handleRunningNode(InstanceNode instanceNode,boolean throwFlagOfNotNext) {
		try {
			logger.info(JsonUtils.toJsonString(instanceNode));
			if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_END) {
				completeInstance(instanceNode);
			}
			else {
				
				//门诊缴费节点
				if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC_PAY) {
					this.genOrderNode(instanceNode);
				}
				
				InstanceRelation relation = new InstanceRelation();
				relation.setInstanceId(instanceNode.getInstanceId());
				relation.setStartNodeId(instanceNode.getId());
				List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
				logger.info(JsonUtils.toJsonString(listRelation));
				if (CollectionUtils.isNotEmpty(listRelation)) {
					boolean hasNext = false;//是否有下一步
					
					for (InstanceRelation thisRelation : listRelation) {
						if (GuideConstants.RELATION_STATUS_PASS.equalsIgnoreCase(thisRelation.getStatus())) {//已经通过的分支
							continue;
						}
						String ruleExp = thisRelation.getRuleExp();
						boolean runNext = true;//符合规则，下一个节点变成运行状态
						if (StringUtils.isNotBlank(ruleExp)) {//定义了规则，验证规则
							
							JSONObject shellParam = JsonUtils.parseObject(JsonUtils.toJsonString(thisRelation));
							Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
							OrderExtVo orderVo = this.getOrderByOrderNo(instance.getOrderNo());
							shellParam.put("order", orderVo);
							
							List<OrderExtVo> payingRecords = this.listGuideInstancePayRecord(instance.getUserId(),instance.getOrgCode(), instance.getPlatformCode(), orderVo.getMedicalCardNo());
							shellParam.put("pay_records", payingRecords);
							
//							List<OrderExtVo> payedRecords = this.listGuideInstancePayedRecord(instance.getOrgCode(), instance.getPlatformCode(), orderVo.getMedicalCardNo(), orderVo.getMedicalCardType());
//							shellParam.put("payed_records", payedRecords);
//							
							shellParam.put("node",instanceNode);
							shellParam.put("relation",thisRelation);
							shellParam.put("instance",instance);
							
							Boolean ruleSuccess = GroovyShellYYT.run(shellParam);
							
							if (ruleSuccess == null) {
								throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "非法规则："+thisRelation.getRuleExp());
							}
							else {
								if (ruleSuccess) {//
									//规则通过
									runNext = true;
									this.passRelation(thisRelation);
								}
								else {
									//规则不通过
									runNext = false;
								}
							}
						}
						else {
							//没有定义规则，则直接通过
							runNext = true;
							this.passRelation(thisRelation);
						}
						//没有定义规则，则默认总是向下一步
						//运行下一步
						logger.info("runNext:"+runNext+","+instanceNode.getNodeName());
						if (runNext) {
							if (StringUtils.isNotBlank(thisRelation.getEndNodeId())) {

								runNode(thisRelation.getEndNodeId());
								hasNext = true;
							}
							else {
								//流程完结,或无下一节点
							}
						}
					}
					if (hasNext) {//有下一步，则此节点运行结束
						logger.info("有下一步:"+instanceNode.getNodeName());
						endNode(instanceNode);
					}
					else {//没有下一步
						logger.info("没有下一步，原地踏步，什么也不做:"+instanceNode.getNodeName());
						//原地踏步，什么也不做
					}
				}
				else {//没有下一步，而且不是终点
					logger.info("没有下一步，而且不是终点:"+instanceNode.getNodeName());
					if (throwFlagOfNotNext) {
						throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "流程异常终结");
					}
					
				}
			}
			logger.info("handleRunningNode--ok");
		
		}
		catch (CallException ae) {
			throw ae;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"处理正在运行的节点异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"处理正在运行的节点异常",ex);
		}
		
		
	}
	
	/**
	 * 旧系统们门诊缴费查询
	 * @param strJson
	 * @return
	 */
	public List<ClinicRecordVo> listClinicRecord(String strJson) {
		logger.info(strJson);
		try{
			JSONObject param = JsonUtils.parseObject(strJson);
			
			if (param.containsKey("hospital_code")) {
				param.put("org_code", param.getString("hospital_code"));
			}

			if (param.containsKey("platform_org_app_code")) {
				param.put("app_code", param.getString("platform_org_app_code"));
			}
			if (param.containsKey("medical_card_no")) {
				param.put("card_no", param.getString("medical_card_no"));
			}
			if (param.containsKey("medical_card_type")) {
				param.put("card_type", param.getString("medical_card_type"));
			}

			if (StringUtils.isBlank(param.getString("user_id")) && StringUtils.isBlank(param.getString("order_no"))) {
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "用户ID和订单号，参数值不能都为空");
			}
			
			ClinicRecordVo clinicRecord = JsonUtils.parseObject(param,ClinicRecordVo.class);
			
			
			StringBuilder sb = new StringBuilder("select * from (");
			for (int k = 1;k<=10;k++) {
				sb.append("select * from biz_clinic_record_"+k+" where 1=1 ");
				
				if (StringUtils.isNotBlank(clinicRecord.getUserId())) {
					sb.append(" and user_id='"+param.getString("user_id")+"'");
				}

				if (StringUtils.isNotBlank(clinicRecord.getOrderNo())) {
					sb.append(" and order_no='"+param.getString("order_no")+"'");
				}
				if (StringUtils.isNotBlank(clinicRecord.getCardNo())) {
					sb.append(" and card_no='"+param.getString("card_no")+"'");
				}
				
				/**
				 * 0待缴费,,1已缴费,,2第三方缴费失败(查询第三方支付接口返回缴费失败),3写入His异常（第三方缴费成功，写入His异常）,4缴费关闭（第三方缴费成功，写入His明确失败，退费给用户成功，则缴费关闭）,
				 * 5退费异常（第三方缴费成功，写入His明确失败，退费给用户失败/异常，这个需要走人工流程）,6写入His失败（第三方缴费成功，写入His失败(中间状态)）,7 业务异常需 人工处理,8业务异常需 窗口处理,
				 * 9用户取消,20窗口退费成功,21窗口退费异常,30窗口部分退费（His发起了，不管成功还是失败，都是部分退费）,31窗口部分退费成功,32窗口部分退费失败,33窗口部分退费异常,34后台退费成功,35后台退费失败,
				 */
				if (StringUtils.isNotBlank(param.getString("clinic_status"))) {
					sb.append(" and clinic_status="+param.getString("clinic_status")+"");
				}
				
				
				if (StringUtils.isNotBlank(clinicRecord.getBeginCreateTime())) {
					sb.append(" and create_time>=UNIX_TIMESTAMP('"+param.getString("begin_create_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(clinicRecord.getEndCreateTime())) {
					sb.append(" and create_time<=UNIX_TIMESTAMP('"+param.getString("end_create_time")+"')*1000");
				}
				
				//org_code必填
//				sb.append(" and hospital_code='"+param.getString("org_code")+"'");
				if (StringUtils.isNotBlank(param.getString("org_code"))) {
					sb.append(" and hospital_code='"+param.getString("org_code")+"'");
				}
				
				if (StringUtils.isNotBlank(param.getString("begin_pay_time"))) {
					sb.append(" and begin_pay_time>=UNIX_TIMESTAMP('"+param.getString("begin_pay_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(param.getString("end_pay_time"))) {
					sb.append(" and end_pay_time<=UNIX_TIMESTAMP('"+param.getString("end_pay_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(clinicRecord.getAppCode())) {
					sb.append(" and app_id='"+param.getString("app_code	")+"'");
				}
				
				
				/**
				 * 1：未支付, 2：已支付3：已退费,4订单支付中,5订单退费中,6订单已经关闭,7未退费
				 */
				if (StringUtils.isNotBlank(param.getString("pay_status"))) {
					sb.append(" and pay_status='"+param.getString("pay_status")+"'");
				}
				
				
				
				if (StringUtils.isNotBlank(param.getString("card_type"))) {
					sb.append(" and card_type='"+param.getString("card_type")+"'");
				}
				
				if (StringUtils.isNotBlank(param.getString("mzfee_id"))) {
					sb.append(" and mzfee_id='"+param.getString("mzfee_id")+"'");
				}
				
				/**
				 * 支付状态，多个用逗号分隔
				 */
				if (StringUtils.isNotBlank(param.getString("clinic_statuss"))) {
					sb.append(" and clinic_status in ("+param.getString("clinic_statuss")+")");
				}
				/**
				 * 支付状态，多个用逗号分隔
				 */
				if (StringUtils.isNotBlank(param.getString("pay_statuss"))) {
					sb.append(" and pay_status in ("+param.getString("pay_statuss")+")");
				}
				
				if (k != 10) {
					sb.append(" union ");
				}
				
			}

			sb.append(") t");
			logger.info(sb.toString());
			List listRegister = BaseService.getBaseClient().queryZhyySql(sb.toString());
			
			if (CollectionUtils.isNotEmpty(listRegister)) {
				return JsonUtils.parseArray(JsonUtils.toJsonString(listRegister), ClinicRecordVo.class);
			}
			return null;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
		}
	
	}
	/**
	 * 获取科室列表信息
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param branchCode
	 * @param orderNos
	 */
	public void listDept(String strJson,String orgCode,String appCode) {
		try{
			
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取科室列表信息执行错误异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取科室列表信息执行错误异常",ex);
		}
	}
	/**
	 * 缴费记录集合
	 * @param strJson
	 * yyt.guide.guideinstance.order.of.clinic.record.list
	 * @return
	 */
	public List<OrderExtVo> listGuideInstanceOrderOfClinicRecord(String strJson) {
		List<ClinicRecordVo> listClinicRecord = this.listClinicRecord(strJson);
		if (CollectionUtils.isNotEmpty(listClinicRecord)) {
			List<OrderExtVo> listOrder = new ArrayList<>();
			for (ClinicRecordVo registerRecord : listClinicRecord) {
				listOrder.add(registerRecord.toOrder());
			}
			return listOrder;
		}
		return Collections.emptyList();
	}
	/**
	 * 获取已缴费记录集合
	 * yyt.guide.guideinstance.payed.record.list
	 * @param strJson
	 * @param orgCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 * @return 不会返回null值
	 */
	public List<OrderExtVo> listGuideInstancePayedRecord(String orgCode,String appCode,String medicalCardNo,Short medicalCardType) {
		try{
			//取24小时内未交费的订单
			Calendar c = Calendar.getInstance();
			c.add(Calendar.DATE, -1);
			
			OrderExtVo order = new OrderExtVo();
			order.setOrgCode(orgCode);
			order.setPlatformOrgAppCode(appCode);
			order.setMedicalCardNo(medicalCardNo);
			order.setMedicalCardType(medicalCardType);
			order.setBeginCreatedTime(GuideConstants.YYYYMMDDHHMMSS.format(c.getTime()));
			order.setPayStatusPayed();
			List<OrderExtVo> listOrder = BaseService.getBaseClient().listOrder(JsonUtils.toJsonString(order));
			if (listOrder == null) {
				listOrder = new ArrayList<>();
			}
			return listOrder;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取已缴费记录集合异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取已缴费记录集合异常",ex);
		}
	}
//	/**
//	 * 从HIS获取挂号信息表
//	 * @param strJson
//	 * @param orgCode
//	 * @param appCode
//	 * @param branchCode
//	 * @param orderNo
//	 */
//	public void getHisRegisterStatus(String strJson,String orgCode,String appCode,String branchCode,String orderNo,Instance instance) {
//		try{
//			//获取状态信息
//			JSONObject jsonInfo = new JSONObject();
//			GuideRegisterStatusVoResponse responseVo = JsonUtils.parseObject(jsonInfo,GuideRegisterStatusVoResponse.class);
//			//同现在有状态对比
//			if ( ! instance.getRegisterStatus().equals(responseVo.getStatus())) {
//				instance.setRegisterStatus(responseVo.getStatus());
//				instanceDao.update(instance);
//				
//				this.runGuideInstance(instance.getId());
//			}
//		}
//		catch (Exception ex) {
//			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从HIS获取挂号信息表执行错误异常",ex);
//			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从HIS获取挂号信息表执行错误异常",ex);
//		}
//	}
	
	/**
	 * 获取缴费记录集合(24小时内）
	 * yyt.guide.guideinstance.pay.record.list
	 * @param strJson
	 * @param orgCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 * @return 不会返回null值
	 */
	public List<OrderExtVo> listGuideInstancePayRecord(String userId,String orgCode,String appCode,String medicalCardNo) {
		try{
			//取24小时内的订单
			Calendar c = Calendar.getInstance();
			c.add(Calendar.DATE, -1);
			
			ClinicRecordVo order = new ClinicRecordVo();
			order.setHospitalCode(orgCode);
			order.setCardNo(medicalCardNo);
			order.setUserId(userId);
//			order.setMedicalCardType(medicalCardType);
			order.setBeginCreateTime(GuideConstants.YYYYMMDDHHMMSS.format(c.getTime()));
			List<OrderExtVo> listOrder = this.listGuideInstanceOrderOfClinicRecord(JsonUtils.toJsonString(order));
			if (listOrder == null) {
				listOrder = new ArrayList<>();
			}
			return listOrder;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取代缴费记录集合异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取代缴费记录集合异常",ex);
		}
	}
	

	public List<OrderExtVo> listGuideInstancePayRecord_bak(String orgCode,String appCode,String medicalCardNo,Short medicalCardType) {
		try{
			//取24小时内未交费的订单
			Calendar c = Calendar.getInstance();
			c.add(Calendar.DATE, -1);
			
			OrderExtVo order = new OrderExtVo();
			order.setOrgCode(orgCode);
			order.setPlatformOrgAppCode(appCode);
			order.setMedicalCardNo(medicalCardNo);
			order.setMedicalCardType(medicalCardType);
			order.setBeginCreatedTime(GuideConstants.YYYYMMDDHHMMSS.format(c.getTime()));
			List<OrderExtVo> listOrder = BaseService.getBaseClient().listOrder(JsonUtils.toJsonString(order));
			if (listOrder == null) {
				listOrder = new ArrayList<>();
			}
			return listOrder;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取代缴费记录集合异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取代缴费记录集合异常",ex);
		}
	}
	
	/**
	 * 
	 * yyt.guide.guideinstance.register.record.list
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param medicalCardNo
	 * @param medicalCardType
	 */
	public List<OrderExtVo> listGuideInstanceRegisterRecord(String strJson) {
		try{
			
			List<RegisterRecord> listRegisterRecord = listRegisterRecord(strJson);
			if (CollectionUtils.isNotEmpty(listRegisterRecord)) {
				List<OrderExtVo> listOrder = new ArrayList<OrderExtVo>();
				for (RegisterRecord registerRecord : listRegisterRecord) {
					listOrder.add(registerRecord.toOrder());
					
				}
				
				return listOrder;
			}
			else {
				return Collections.EMPTY_LIST;
			}
//			JSONObject order = JsonUtils.parseObject(strJson);
//			
//			order.put("order_type","1");
//			if (StringUtils.isBlank(order.getString("order_columns"))) {
//				order.put("order_columns","schedule_time desc");
//			}
//			
//			return BaseService.getBaseClient().listOrder(JsonUtils.toJsonString(order));

		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"导医的挂号信息列表异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"导医的挂号信息列表异常",ex);
		}
	}
	/**
	 * 批量从HIS获取挂号信息表
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param branchCode
	 * @param orderNo
	 */
	public void listHisRegisterStatus(String strJson,String orgCode,String appCode,String branchCode,String orderNos,List<Instance> listInstance) {
		try{
			//获取状态信息
			JSONArray jsonArr = new JSONArray();
			
			int size = jsonArr.size();
			for (int i = 0;i<size;i++) {
				GuideRegisterStatusVoResponse responseVo = JsonUtils.parseObject(jsonArr.getJSONObject(i),GuideRegisterStatusVoResponse.class);
				for (Instance instance : listInstance) {
					if (instance.getOrderNo().equals(responseVo.getYytOrdNum())) {
						//同现在有状态对比
						if ( ! instance.getRegisterStatus().equals(responseVo.getStatus())) {
							instance.setRegisterStatus(responseVo.getStatus());
							instanceDao.update(instance);
							
							this.runGuideInstance(instance.getId());
						}
					}
				}
				
			}
			}
			
			
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"批量从HIS获取挂号信息表执行错误异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"批量从HIS获取挂号信息表执行错误异常",ex);
		}
	}
	
	/**
	 * 
	 * 获取医院列表信息
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param branchCode
	 * @param orderNos
	 */
	public void listHistory(String strJson) {
		try {
			
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"获取医院列表信息执行错误异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"获取医院列表信息执行错误异常",ex);
		}
	}
	
	public List<OrderExtVo> listOrder(String strJson) {
		List<RegisterRecord> listRegisterRecord = this.listRegisterRecord(strJson);
		if (CollectionUtils.isNotEmpty(listRegisterRecord)) {
			List<OrderExtVo> listOrder = new ArrayList<>();
			for (RegisterRecord registerRecord : listRegisterRecord) {
				listOrder.add(registerRecord.toOrder());
			}
			return listOrder;
		}
		return Collections.emptyList();
	}
	
	/**
	 * 从旧系统获取挂号信息
	 * @param strJson
	 * @param user_id
	 * @param begin_schedule_time
	 * @param end_schedule_time
	 * @throws 可能返回null值
	 */
	public List<RegisterRecord> listRegisterRecord(String strJson) {

		try{
			JSONObject param = JsonUtils.parseObject(strJson);
			if (param.containsKey("schedule_time")) {
				param.put("schedule_date", param.getString("schedule_time"));
			}
			if (param.containsKey("begin_schedule_time")) {
				param.put("begin_schedule_date", param.getString("begin_schedule_time"));
			}
			if (param.containsKey("end_schedule_time")) {
				param.put("end_schedule_date", param.getString("end_schedule_time"));
			}
			
			if (param.containsKey("hospital_code")) {
				param.put("org_code", param.getString("hospital_code"));
			}

			if (param.containsKey("platform_org_app_code")) {
				param.put("app_code", param.getString("platform_org_app_code"));
			}
			if (param.containsKey("medical_card_no")) {
				param.put("card_no", param.getString("medical_card_no"));
			}
			if (param.containsKey("medical_card_type")) {
				param.put("card_type", param.getString("medical_card_type"));
			}
			
			//创建时间，转换为挂号时间
			if (param.containsKey("begin_created_time")) {
				param.put("begin_register_time", param.getString("begin_created_time"));
			}
			if (param.containsKey("end_created_time")) {
				param.put("end_register_time", param.getString("end_created_time"));
			}
			
			
			StringBuilder sb = new StringBuilder("select * from (");
			for (int k = 1;k<=10;k++) {
				sb.append("select * from biz_register_record_"+k+" where user_id='"+param.getString("user_id")+"'");

				if (StringUtils.isNotBlank(param.getString("order_no"))) {
					sb.append(" and order_no='"+param.getString("order_no")+"'");
				}
				if (StringUtils.isNotBlank(param.getString("card_no"))) {
					sb.append(" and card_no='"+param.getString("card_no")+"'");
				}
				
				/**
				 * 挂号状态：0: 预约中,1: 已预约,2: 用户取消,3: 支付超时取消,4: 停诊取消,5: 预约异常(his锁号异常),6: 第三方支付异常,
				 * 7: 支付确认异常,8: 取消挂号异常,9: 退费前确认异常,10: 第三方退费异常,11: 退费后确认异常,12: 挂号失败,
				 * 13: 异常轮询处理成功,14: 业务异常  需人工处理,15: 业务异常  需窗口处理,16: 停诊取消异常 未支付,
				 * 17: 停诊预约退费确认异常,18: 停诊第三方退费异常,19: 停诊退费后确认异常,20: 窗口退费成功,21: 窗口退费异常,23: 后台退费成功,24: 后台退费失
				 */
				if (StringUtils.isNotBlank(param.getString("reg_status"))) {
					sb.append(" and reg_status='"+param.getString("reg_status")+"'");
				}
				
				
				if (StringUtils.isNotBlank(param.getString("begin_register_time"))) {
					sb.append(" and register_time>=UNIX_TIMESTAMP('"+param.getString("begin_register_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(param.getString("end_register_time"))) {
					sb.append(" and register_time<=UNIX_TIMESTAMP('"+param.getString("end_register_time")+"')*1000");
				}
				
				//org_code必填
				sb.append(" and hospital_code='"+param.getString("org_code")+"'");
				
				if (StringUtils.isNotBlank(param.getString("begin_schedule_time"))) {
					sb.append(" and schedule_date>='"+param.getString("begin_schedule_time")+"'");
				}
				if (StringUtils.isNotBlank(param.getString("end_schedule_time"))) {
					sb.append(" and schedule_date<='"+param.getString("end_schedule_time")+"'");
				}
				if (StringUtils.isNotBlank(param.getString("reg_type"))) {
					sb.append(" and reg_type='"+param.getString("reg_type")+"'");
				}
				
				if (StringUtils.isNotBlank(param.getString("begin_pay_time"))) {
					sb.append(" and begin_pay_time>=UNIX_TIMESTAMP('"+param.getString("begin_pay_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(param.getString("end_pay_time"))) {
					sb.append(" and end_pay_time<=UNIX_TIMESTAMP('"+param.getString("end_pay_time")+"')*1000");
				}
				if (StringUtils.isNotBlank(param.getString("app_code"))) {
					sb.append(" and app_id='"+param.getString("app_code")+"'");
				}
				
				
				/**
				 * 支付状态：1：未支付, ,2：已支付,3：已退费,4: 支付中,5:订单退费中,6:订单已关闭,7:未退费
				 */
				if (StringUtils.isNotBlank(param.getString("pay_status"))) {
					sb.append(" and pay_status='"+param.getString("pay_status")+"'");
				}
				
				
				
				if (StringUtils.isNotBlank(param.getString("card_type"))) {
					sb.append(" and card_type='"+param.getString("card_type")+"'");
				}
				
				if (StringUtils.isNotBlank(param.getString("mz_fee_id"))) {
					sb.append(" and mz_fee_id='"+param.getString("mz_fee_id")+"'");
				}
				
				if (k != 10) {
					sb.append(" union ");
				}
				
			}
			sb.append(") t order by schedule_date desc");
			List listRegister = BaseService.getBaseClient().queryZhyySql(sb.toString());
			if (CollectionUtils.isNotEmpty(listRegister)) {
				return JsonUtils.parseArray(JsonUtils.toJsonString(listRegister), RegisterRecord.class);
			}
			return null;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"从旧系统获取挂号列表信息异常",ex);
		}
	
	}
	
	/**
	 * 修改分支状态：通过
	 * @param instanceRelation
	 */
	private void passRelation(InstanceRelation instanceRelation) {
		instanceRelation.setStatus(GuideConstants.RELATION_STATUS_PASS);
		instanceRelationDao.update(instanceRelation);
	}
	
	
	/**
	 * 刷新地址信息
	 * yyt.guide.guideinstance.address.info.reflesh
	 * @param nodeId
	 * @return 如果没有变化，返回null，否则返回整个流程信息
	 */
	public void refleshGuideInstanceAddressInfo(String orderNo) {
		logger.info(orderNo);
		if (orderNo.startsWith("{")) {
			JSONObject param = JsonUtils.parseObject(orderNo);
			orderNo = param.getString("order_no");
		}
		if (StringUtils.isBlank(orderNo)) {
			logger.error("orderNo为空");
			return;
		}
		
		InstanceNode queryNode = new InstanceNode();
		queryNode.setOrderNo(orderNo);
		List<InstanceNode> listNode = instanceNodeDao.select(queryNode);
		if (CollectionUtils.isNotEmpty(listNode)) {
			List<ClinicAddressInfoVoResponse> listAddressInfo = getGuideInstanceHisAddressInfo(orderNo);
			
			if (CollectionUtils.isNotEmpty(listAddressInfo)) {
				InstanceNode instanceNode = listNode.get(0);
				logger.info("路由更新：");
				this.genAddressNode(instanceNode.getId(), listAddressInfo);
				this.handleRunningNode(instanceNode, false);
				
			}
		}
		
	}
	
	/**
	 * 刷新
	 * yyt.guide.guideinstance.status.reflesh
	 * @param instanceId
	 * @return 如果没有变化，返回null，否则返回整个流程信息
	 */
	public Instance refleshGuideInstanceStatus(String orderNo) {
		logger.info(orderNo);
		if (orderNo.startsWith("{")) {
			JSONObject param = JsonUtils.parseObject(orderNo);
			orderNo = param.getString("order_no");
		}
		if (StringUtils.isBlank(orderNo)) {
			logger.error("orderNo为空");
			return null;
		}
		
		Instance queryInstance = new Instance();
		queryInstance.setOrderNo(orderNo);
		List<Instance> listInstance = instanceDao.select(queryInstance);
		if (CollectionUtils.isEmpty(listInstance)) {
			logger.error(orderNo+"对应的导医不存在");
			return null;
		}
		Instance instance = listInstance.get(0);
		
		
		RegisterGuideInfoVoResponse registerGuideInfoVoResponse = this.getHisRegisterStatus(instance);
		if (registerGuideInfoVoResponse != null) {

			RegisterStatus registerStatus = new RegisterStatus();
			registerStatus.setOrgCode(instance.getOrgCode());
			registerStatus.setHisRegisterStatusCode(registerGuideInfoVoResponse.getStatus());
			List<RegisterStatus> listRegisterStatus = registerStatusDao.select(registerStatus);
			
			if (CollectionUtils.isEmpty(listRegisterStatus)) {
				logger.error("没有找到对应的挂号状态对应关系:"+JsonUtils.toJsonString(registerStatus));
				//没有状态就没有变化
				return null;
			}
			else {
				registerStatus = listRegisterStatus.get(0);
				
				if ( ! instance.getRegisterStatus().equals(registerStatus.getPlatformRegisterStatusCode())) {
	
					logger.info("状态更新："+instance.getRegisterStatus()+"--->>"+registerStatus.getPlatformRegisterStatusCode()+",order_no="+instance.getOrderNo());
					instance.setRegisterStatus(registerStatus.getPlatformRegisterStatusCode());
					instance.setRegisterStatusName(registerStatus.getPlatformRegisterStatusName());
					instanceDao.update(instance);
					
					//就诊结束
					if (GuideConstants.REGISTER_STATUS_NED_VISIT.equals(instance.getRegisterStatus())) {
						
						this.stopGuideInstance(JsonUtils.toJsonString(instance));
					}
					else {
						this.runGuideInstance(instance.getId());
					}
					
				}
				else {
					//没有状态变化
					return null;
				}
				
			}
			
			return this.getGuideInstanceFull(instance.getId());
		}
		return null;
		
	}
	
	
	/**
	 * 让某个流程继续运行起来
	 * @param strJson
	 * @param instanceId
	 */
	public void runGuideInstance(String instanceId) {
		try {
			logger.info("runGuideInstance:"+instanceId);

			Instance instance = instanceDao.selectById(instanceId);
			if (instance != null && instance.getRunStatus().equals(GuideConstants.INSTANCE_RUN_STATUS_RUNNING)) {
				
				
				InstanceNode node = new InstanceNode();
				node.setInstanceId(instanceId);
				node.setRunStatus(GuideConstants.NODE_RUN_STATUS_RUNNING);
				List<InstanceNode> listNode = instanceNodeDao.select(node);
				logger.info(JsonUtils.toJsonString(listNode));
				if (CollectionUtils.isNotEmpty(listNode)) {
					for (InstanceNode thisNode : listNode) {
						this.handleRunningNode(thisNode, false);
					}
				}
			}
			logger.info("runGuideInstance--ok");
		}
		catch (CallException ae) {
			throw ae;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"让某个流程继续运行起来异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"让某个流程继续运行起来异常",ex);
		}
		
	}
	/**
	 * 让某个流程继续运行起来
	 * @param strJson
	 * @param instanceId
	 */
	public void runGuideInstanceByOrderNo(String orderNo) {
		try {
			logger.info("orderNo:"+orderNo);

			Instance instance = new Instance();
			instance.setOrderNo(orderNo);
			List<Instance> listInstance = instanceDao.select(instance);
			if (CollectionUtils.isNotEmpty(listInstance)) {
				runGuideInstance(listInstance.get(0).getId());
			}
			
			logger.info("runGuideInstanceByOrderNo--ok");
		}
		catch (CallException ae) {
			throw ae;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"让某个流程继续运行起来异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"让某个流程继续运行起来异常",ex);
		}
		
	}
	/**
	 * 将某个节点激活，即运行到某个节点
	 * @param instanceNode
	 */
	private void runNode(InstanceNode instanceNode) {
		logger.info(JsonUtils.toJsonString(instanceNode));
		InstanceRelation relation = new InstanceRelation();
		relation.setInstanceId(instanceNode.getInstanceId());
		relation.setEndNodeId(instanceNode.getId());
		List<InstanceRelation> listRelation = instanceRelationDao.select(relation);
		if (CollectionUtils.isEmpty(listRelation)) {
			logger.error("没有来源分支");
//			return;
		}
		int relationCount = listRelation.size();
		int hasCompleteRelationCount = 0;
		for (InstanceRelation thisRelation : listRelation) {
			if (GuideConstants.RELATION_STATUS_PASS.equalsIgnoreCase(thisRelation.getStatus())) {
				hasCompleteRelationCount++;
			}
		}
		
		boolean startRunFlag = parseRunRule(instanceNode.getStartRunRule(), relationCount, hasCompleteRelationCount);
		logger.info("startRunFlag="+startRunFlag);
		if (startRunFlag) {
			logger.info("符合启动条件："+instanceNode.getNodeName());
			instanceNode.setRunStatus(GuideConstants.NODE_RUN_STATUS_RUNNING);
			instanceNode.setStartTime(GuideConstants.YYYYMMDDHHMMSS.format(new Date()));
			
			if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_WAIT_VISIT) {
				String msg = "您已进入候诊队列，请耐心等待";
				instanceNode.setRemarks(msg);
//				Instance instance = instanceDao.selectById(instanceNode.getInstanceId());
//				DeptPosition deptPosition = deptPositionDao.getPosition(instance.getOrgCode(),instance.getDeptCode());
//				if (deptPosition != null) {
//					instanceNode.setRemarks("请到"+deptPosition.getPosition() + instance.getDeptName()+"候诊");
//				}
//				else {
//					instanceNode.setRemarks("请到"+instance.getDeptName()+"候诊");
//				}
				
			}
//			else if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_CLINIC) {
//				String msg = "您有N笔待缴费（总金额）";
//				instanceNode.setRemarks(msg);
//
//				
//			}
//			else if (instanceNode.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_BY_ORDER) {
//				String msg = "您有一笔待缴费（金额）";
//				instanceNode.setUrl("?order_no=");//listItem 地址
//				instanceNode.setRemarks(msg);
//				
//				//待缴费：金额
//				//已缴费：HIS信息决定
//
//				
//			}
	
			instanceNodeDao.update(instanceNode);
			
			handleRunningNode(instanceNode,false);
			
		}
		
		
		logger.info("runNode--ok");
	}
	
	/**
	 * 将某个节点激活，即运行到某个节点
	 * @param nodeId
	 */
	private void runNode(String nodeId) {
		InstanceNode node = instanceNodeDao.selectById(nodeId);
		runNode(node);
		logger.info("runNode--ok");
	}
	
	/**
	 * 启动一个导医流程
	 * yyt.guide.guideinstance.start
	 * @param strJson
	 * @param order_no
	 * @param user_id
	 * @return
	 */
	public Instance startGuideInstance(String strJson) {
		JSONObject param = JsonUtils.parseObject(strJson);
		return startGuideInstanceReal(param.getString("order_no"));
	}
	/**
	 * 启动一个导医流程
	 * <br>yyt.guide.guideinstance.start
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param templateId
	 * @param orderNo
	 * @param userId
	 * @return Instance
	 */
	public Instance startGuideInstanceReal(String orderNo) {

		try {
			logger.info("orderNo="+orderNo);
			
			OrderExtVo orderVo = this.getOrderByOrderNo(orderNo);
			if (orderVo == null) {
				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "订单不存在");
			}
			if (orderVo.getOrderType() != OrderExtVo.ORDER_TYPE_REGISTER) {
//				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "必须是挂号订单才可以生成导医流程");
			}
			String userId = orderVo.getUserId();
			//获取匹配的模板信息
			Template template = templateDao.selectForMatch(orderVo.getOrgCode(), orderVo.getPlatformCode(), orderVo.getDeptCode());
			if (template == null) {
				throw new CallException(ErrorCodeDefine.GUIDE_NOT_EXIST_TEMPLATE, "无匹配的模板");
			}
			String templateId = template.getId();
			
			//检查是否已经有导医
			Instance instance = new Instance();
			instance.setOrgCode(orderVo.getOrgCode());
//			instance.setPlatformCode(platformAppCode);
			instance.setOrderNo(orderNo);
			List<Instance> existInstances = instanceDao.select(instance);
			if (CollectionUtils.isNotEmpty(existInstances)) {
				this.runGuideInstance(existInstances.get(0).getId());
				return getGuideInstanceFull(existInstances.get(0).getId());
//				throw new CallException(ErrorCodeDefine.GUIDE_COMMON, "已经有导医流程");
			}
			
			template = guideTemplateService.getFullTemplate(templateId);
			instance = JsonUtils.parseObject(template,Instance.class);
			instance.setOrderNo(orderNo);
			instance.setUserId(userId);
			instance.setId(IDUtils.getUUID32());
			instance.setTemplateId(templateId);
			instance.setMzFeeId(orderVo.getMzFeeId());
//			instance.setHospitalId(orderVo.getHospitalId());
			
			Map<String,String> mapR = new HashMap<>();
			
			instance.setDeptCode(orderVo.getDeptCode());
			instance.setDeptName(orderVo.getDeptName());
			instance.setRunStatus(GuideConstants.INSTANCE_RUN_STATUS_RUNNING);
			instance.setCreatedTime(GuideConstants.YYYYMMDDHHMMSS.format(Calendar.getInstance().getTime()));
			
			instance.setValidFlag(1);
			
			instance.setPatCardNo(orderVo.getMedicalCardNo());
			instance.setPatCardType("2");//orderVo.getMedicalCardType();订单表和HIS之间含义不一样，固定为2
			instance.setRegisterStatus(GuideConstants.REGISTER_STATUS_PAYED);
			instance.setRegisterStatusName("已挂号");
			
			
			
			List<InstanceNode> listNode = instance.getListNode();
			for (InstanceNode node : listNode) {
				node.setTemplateNodeId(node.getId());
				node.setId(IDUtils.getUUID32());
				mapR.put(node.getTemplateNodeId(), node.getId());
				node.setInstanceId(instance.getId());
				node.setRunStatus(GuideConstants.NODE_RUN_STATUS_NOT_START);
				
				//挂号节点，设置显示信息
				if (node.getNodeProcType() == GuideConstants.NODE_PROC_TYPE_REGISTER) {
					String remarks = null;
					RegisterGuideInfoVoResponse registerGuideInfoVoResponse = this.getHisRegisterStatus(instance);
					if (registerGuideInfoVoResponse != null) {
						remarks = "挂号\n"+orderVo.getDeptName()+"-"+orderVo.getDoctorName() + "\n" +"请到"+registerGuideInfoVoResponse.getDeptLocal() +"就诊\n排队号："+registerGuideInfoVoResponse.getQueueSn();
					}
					else {
						remarks = "挂号\n"+orderVo.getDeptName()+"-"+orderVo.getDoctorName();
					}
					node.setRemarks(remarks);
					instance.setHisStatusInfo(JsonUtils.toJsonString(orderVo));
				}
				
				instanceNodeDao.insert(node);
				
			}
			
			
			instanceDao.insert(instance);
			
			List<InstanceRelation> listRelation = instance.getListRelation();
			for (InstanceRelation relation : listRelation) {
				relation.setTemplateRelationId(relation.getId());
				relation.setId(IDUtils.getUUID32());
				relation.setInstanceId(instance.getId());		
				relation.setStartNodeId(mapR.get(relation.getStartNodeId()));
				relation.setEndNodeId(mapR.get(relation.getEndNodeId()));
				instanceRelationDao.insert(relation);
			}
			
			runNode(listNode.get(0));
			
			logger.info("startGuideInstance--ok");
			
			return this.getGuideInstanceFull(instance.getId());
		}
		catch (CallException ae) {
			throw ae;
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"启动一个导医流程异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"启动一个导医流程异常",ex);
		}
	}
	
	/**
	 * 手动结束/中断流程
	 * yyt.guide.guideinstance.stop
	 * @param strJson
	 * @param orgCode
	 * @param appCode
	 * @param instanceId
	 */
	public String stopGuideInstance(String strJson) {
		try {
			JSONObject param = JsonUtils.parseObject(strJson);
			String instanceId = param.getString("instance_id");
			Instance instance = instanceDao.selectById(instanceId);
			if (instance != null && instance.getRunStatus().equals(GuideConstants.INSTANCE_RUN_STATUS_RUNNING)) {
				instance.setRunStatus(GuideConstants.INSTANCE_RUN_STATUS_STOP);
				instanceDao.update(instance);
	
			}
			else {
				return "导医已经结束";
			}
		}
		catch (Exception ex) {
			logger.error(ErrorCodeDefine.GUIDE_COMMON,"手动结束/中断流程异常",ex);
			throw new CallException(ErrorCodeDefine.GUIDE_COMMON,"手动结束/中断流程异常",ex);
		}
		return "SUCCESS"; 
	}
}
